/*
	gToastMsg - 无图标文字提示
	gToastSuccess - 成功提示
	gToastError - 错误提示
	gShowModal - 确认提示
	gUploadFile - 上传文件
	gGetFileUrl - 获取文件路径
	gformatDate - 格式化日期输出
	gLoading - 显示/隐藏加载动画
	$menuPicker - 调用菜单选择框
	$chooseImage - 选择图片
	$readImgs - 预览图片
	gIsNull - 判断输入是否为空
  $setData - 批量设置data数据
*/
import Vue from 'vue'
import COS from '@/static/COS.js'
import router from '@/utils/link'
import stores from '@/store'

let loading = false // 是否有loading动画。因为微信小程序的坑，如果调用了showLoading,再调用success，会直接提示success，如果后面再调用hideLoading，会直接把success提示关掉
/**
 * 展示加载动画
 * @param {String} text
 * @param {Boolean} mask 是否有蒙层
 */

Vue.prototype.$loading = (text = '加载中', mask = true) => {
  loading = true
  uni.showLoading({
    title: text,
    mask
  })
}
/**
 * 隐藏加载动画
 * @param {Number}
 */
Vue.prototype.$hideLoading = (delay = 0) => {
  if (!loading) { // 没有loading动画不执行
    return
  }
  if (delay > 0) {
    setTimeout(() => {
      uni.hideLoading()
    }, delay)
  } else {
    uni.hideLoading()
  }
  loading = false
}

/**
 * 普通文本提示，无图标
 * @param {String}  title 内容
 * @param {Boolean}  mask 是否展示蒙层
 * @param {Number}  duration
 */
Vue.prototype.$msg = (title, mask = false, duration = 1500) => {
  loading = false
  uni.showToast({
    title,
    mask,
    duration,
    icon: 'none'
  })
}

/**
 * 成功文本提示，打钩图标
 * @param {String}  title 内容
 * @param {Boolean}  mask 是否展示蒙层
 * @param {Number}  duration
 */
Vue.prototype.$success = (title, mask = false, duration = 1500) => {
  loading = false
  uni.showToast({
    title,
    mask,
    duration,
    icon: 'success'
  })
}

/**
 * 展示错误提示，错误图标
 * @param {String}  title 内容
 * @param {Boolean}  mask 是否展示蒙层
 * @param {Number}  duration
 */
Vue.prototype.$error = (title, mask = false, duration = 1500) => {
  loading = false
  uni.showToast({
    title,
    icon: 'error',
    mask,
    duration
  })
}

/**
 * 提示确认操作
 * @param {String}  content 提示文字
 * @param {Function}  success 确认后操作
 * @param {Function}  cancel 取消后操作
 */
Vue.prototype.$confirm = (content, success, cancel) => {
  uni.showModal({
    title: '提示',
    content,
    confirmColor: '#6782f1',
    success: (res) => {
      if (res.confirm && success) {
        success()
      } else if (res.cancel && cancel) {
        cancel()
      }
    }
  })
}

/**
 * 上传文件
 * @param {String}  filePath
 * @param {Object}  signature 签名
 * @param {Function}  上传期间回调函数，用于监听进度，参数为上传进度
 * @return {Object} 上传完成回调，可以从header获取到上传地址
 */
Vue.prototype.gUploadFile = (filePath, signature, updateDom = null) => new Promise((resolve, reject) => {
  const uploadTask = uni.uploadFile({
    url: `https://${ signature.bucketName }.cos.${ signature.region }.myqcloud.com/`,
    name: 'file',
    filePath: filePath,
    formData: {
      'key': signature.filename,
      'policy': signature.policy,
      'q-sign-algorithm': 'sha1',
      'q-ak': signature.secretId,
      'q-key-time': signature.keyTime,
      'q-signature': signature.signature
    },
    success: (res) => {
      if (res.statusCode === 204) {
        resolve(res)
      }
      reject(res)
    },
    fail: (err) => {
      reject(err)
    }
  })

  uploadTask.onProgressUpdate((res) => {
    if (updateDom) {
      updateDom(res.progress)
    }
  })
})

/**
 * 获取文件路径
 * @param {Object}  signature 签名
 * @return {String} 文件路径
 */
Vue.prototype.gGetFileUrl = (signature) => new Promise((resolve, reject) => {
  const cos = new COS({
    getAuthorization: function(options, callback) {
      callback({
        Authorization: signature.authorization
      })
    }
  })
  /* 获取数据 */

  cos.getObjectUrl({
    Bucket: signature.bucketName,
    Region: signature.region,
    Key: signature.filename,
    Sign: true,
    Expires: 60,
  }, (err, data) => {
    if (err) {
      reject(err)
    }
    resolve(data.Url)
  })
})

/**
 * 调用menu弹窗进行单选,将选择的结果返回
 * @param {Array}  list 可以为一维简单数组，也可以为对象数组，对象必须包含label
 * @return {any}  选中的元素
 */
Vue.prototype.$menuPicker = (list = []) => new Promise((resolve, reject) => {
  uni.showActionSheet({
    itemList: typeof list[ 0 ] === 'object' ? list.map(item => item.label) : list,
    success: (res) => {
      resolve(list[ res.tapIndex ])
    },
    fail: (err) => {
      reject(err)
    }
  })
})

/**
 * 选择图片
 * @param {Number}  count 图片数量
 * @param {Boolean}  original 是否可选原图
 * @return {String} 图片地址
 */
Vue.prototype.$chooseImage = (count = 1, original = false) => new Promise((resolve, reject) => {
  uni.chooseImage({
    count, // 默认9
    sizeType: original ? ['original', 'compressed'] : ['compressed']
  })
    .then(img => {
      if (img[ 0 ] && img[ 0 ].errMsg === 'chooseImage:fail cancel') {
        reject('cancel choose')
      } else {
        resolve(img[ 1 ].tempFilePaths)
      }
    })
    .catch(err => reject(err))
})

/**
 * 预览图片
 * @param {Array}  urls 图片列表
 * @param {Number}  current 开始下标
 */
Vue.prototype.$readImgs = (urls, current = 0) => {
  uni.previewImage({
    current,
    urls
  })
}

/**
 * 判断数据是否为空
 * @param {Array}  list 数组对象，必须包含val和errMsg值，检测val为空时提示errMsg
 * @return {Boolean}
 */
Vue.prototype.gIsNull = (list) => {
  for (let i = 0; i < list.length; i++) {
    if (!list[ i ].val) {
      Vue.prototype.$msg(list[ i ].errMsg)
      return true
    }
  }
  return false
}

/**
 * 设置data里的数据（必须用function，否则this指向错误）
 * @param {Object} params
 */
Vue.prototype.$setData = function(params) {
  for (const key in params) {
    this[ key ] = params[ key ]
  }
}

/**
 * 路由跳转
 */
Vue.prototype.$router = router
Vue.prototype.$navigateTo = function(url, success, fail) {
  uni.navigateTo({
    url, success,
    fail: (e) => {
      console.log(e)
      fail && fail()
    }
  })
}

/**
 * 输入一个方法，判断是否可执行，可执行则直接执行
 */
Vue.prototype.$checkFn = function(cb) {
  typeof cb === 'function' && cb()
}

/**
  * 获取对应桶state值
  * @param {String} name 存储桶名称
  * @param {String} key key值
  */
Vue.prototype.$getState = function(name, key) {
  // eslint-disable-next-line no-prototype-builtins
  if (stores.state.hasOwnProperty(name) && stores.state[ name ].hasOwnProperty(key)) {
    return stores.state[ name ][ key ]
  }
  return ''
}

/**
  * 获取对应桶getter值
  * @param {String} name getters名
  */
Vue.prototype.$storeGet = function(name) {
  // eslint-disable-next-line no-prototype-builtins
  if (stores.getters.hasOwnProperty(name)) {
    return stores.getters[ name ]
  }
  return ''
}

/**
  * commit方法
  * @param {String} name commit方法名！！
  * @param {Any} params 参数
  */
Vue.prototype.$storeCommit = function(name, params) {
  stores.commit(name, params)
}
/**
  * actions方法
  * @param {String} name action方法名!!
  * @param {Any} params 参数
  */
Vue.prototype.$storeAction = function(name, params) {
  return stores.dispatch(name, params)
}

/**
 * 分页数据处理，只能在vue页面使用，this指向当前页data，保证pageNum,total字段有效
 * @param {Function} request 请求
 * @param {Number} pageNum 页码
 * @param {String} key 数据的key值
 */
Vue.prototype.$pageDataSet = async function({ request, pageNum, key, adapt }) {
  try {
    this.loadStatus = 'loading'

    const res = await request()

    const pageData = typeof adapt === 'function'
      ? await Promise.all(res.pageData.map(item => adapt(item)))
      : res.pageData
    const result = pageNum === 1 ? pageData : this[ key ].concat(pageData)

    this.total = res.total
    this.pageNum = pageNum
    if (result.length < this.total) {
      this.loadStatus = 'loadmore'
    } else {
      this.loadStatus = 'nomore'
    }
    return result
  } catch (err) {
    this.loadStatus = 'nomore'
    return Promise.reject(err)
  }
}
